package com.untour.im.client;

import com.untour.im.client.handler.policy.ExponentialBackOffRetry;
import com.untour.im.client.handler.policy.RetryPolicy;
import com.untour.im.client.listener.ClientChannelFutureListener;
import com.untour.im.common.enums.ClientType;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import lombok.Getter;
import lombok.Setter;

public class TcpClient {

    private final String host;
    private final int port;
    @Getter
    private final int clientType;
    @Getter
    @Setter
    private boolean forceOffline = false;
    private Bootstrap bootstrap;
    private NioEventLoopGroup group;
    /**
     * 重连策略
     */
    @Getter
    private final RetryPolicy retryPolicy;
    /**
     * 将<code>Channel</code>保存起来, 可用于在其他非handler的地方发送数据
     */
    private Channel channel;

    public TcpClient(String host, int port,int clientType) {
        this(host, port,clientType,
                new ExponentialBackOffRetry(1000,
                        Integer.MAX_VALUE, 60 * 1000));
    }

    public TcpClient(String host, int port,int clientType, RetryPolicy retryPolicy) {
        this.host = host;
        this.port = port;
        this.clientType = clientType;
        this.retryPolicy = retryPolicy;
        this.init();
    }

    /**
     * 向远程TCP服务器请求连接
     */
    public void connect() {
        synchronized (bootstrap) {
            ChannelFuture future = bootstrap.connect(host, port);
            future.addListener(this.getConnectionListener());
            this.channel = future.channel();
        }
    }

    public void close(ChannelHandlerContext ctx){
        System.err.println("强制下线~~~~");
        channel.close();
        ctx.close();
        ctx.channel().close();
        group.shutdownGracefully();
        System.exit(1);
    }

    private void init() {
        group = new NioEventLoopGroup();
        // bootstrap 可重用, 只需在TcpClient实例化的时候初始化即可.
        bootstrap = new Bootstrap();
        bootstrap.group(group)
                .channel(NioSocketChannel.class)
                .handler(new ClientHandlersInitializer(this));
    }

    private ChannelFutureListener getConnectionListener() {
        return new ClientChannelFutureListener();
    }

    public static void main(String[] args) {
        TcpClient tcpClient = new TcpClient("localhost", 2222, ClientType.MAC.getValue());
        tcpClient.connect();
    }
}